<template>
  <transition name="slide-left">
    <div v-if="visible" class="node-panel-drawer" @mouseleave="minimize">
      <div class="drawer-header">
        <span class="search-icon">🔍</span>
        <input v-model="search" placeholder="搜索节点" class="search-input" />
        <button class="min-btn" @click="minimize"><span>«</span></button>
      </div>
      <div class="drawer-categories">
        <div v-for="cat in categories" :key="cat.key" class="category">
          <div class="cat-title">
            <span
              class="cat-bar"
              :style="{ background: catColors[cat.key] }"
            ></span
            >{{ cat.label }}
          </div>
          <div class="node-list">
            <div
              v-for="node in filteredNodes(cat.key)"
              :key="node.type"
              class="node-item"
              :style="{
                borderLeft: '6px solid ' + catColors[node.category],
                boxShadow: '0 2px 8px rgba(0,0,0,0.08)',
              }"
              draggable="true"
              @dragstart="onDragStart(node, $event)"
              @click="onNodeSelect(node)"
            >
              <span
                class="node-icon"
                :style="{ background: catColors[node.category] }"
                >{{ node.icon }}</span
              >
              <span class="node-label">{{ node.label }}</span>
            </div>
          </div>
        </div>
      </div>
    </div>
    <div v-else class="node-panel-mini" @mouseenter="expand">
      <span>»</span>
    </div>
  </transition>
</template>

<script setup lang="ts">
import { ref, watch } from "vue";

const emit = defineEmits<{
  (e: "visibility-change", visible: boolean): void;
  (e: "node-select", node: any): void;
}>();

// 由父组件可控的可见性
const props = defineProps<{ visible?: boolean }>();
const visible = ref(false);
const search = ref("");
const categories = [
  { key: "form", label: "表单" },
  { key: "auto", label: "自动化节点" },
  { key: "approval", label: "审批" },
  // { key: "custom", label: "自定义" },
  { key: "condition", label: "条件" },
  { key: "control", label: "控制" },
];
const catColors = {
  form: "#3b82f6",
  auto: "#8b5cf6",
  approval: "#f59e42",
  basic: "#10b981",
  custom: "#a855f7",
  condition: "#f43f5e",
  control: "#6366f1",
};
const nodes = [
  { type: "form", label: "人工节点", icon: "🟢", category: "form" },
  { type: "auto", label: "自动化节点", icon: "🟡", category: "auto" },
  { type: "approval", label: "审批节点", icon: "📝", category: "approval" },
  { type: "custom", label: "自定义节点", icon: "⚙️", category: "custom" },
  { type: "condition", label: "条件节点", icon: "🔀", category: "condition" },
  { type: "control", label: "控制节点", icon: "🔧", category: "control" },
];
function filteredNodes(catKey: string) {
  return nodes.filter(
    (n) =>
      n.category === catKey && (!search.value || n.label.includes(search.value))
  );
}
function minimize() {
  visible.value = false;
}
function expand() {
  visible.value = true;
}
function onDragStart(node, e) {
  e.dataTransfer.setData("nodeType", node.type);
  e.dataTransfer.setData("nodeCategory", node.category);
}

function onNodeSelect(node) {
  emit("node-select", node);
  minimize(); // 选择节点后自动关闭面板
}

// 监听内部 visible 状态变化，向父组件报告
watch(visible, (newVisible) => {
  emit("visibility-change", newVisible);
});

// 监听父 prop 变化并同步到内部状态
watch(
  () => props.visible,
  (v) => {
    if (typeof v === "boolean") {
      visible.value = v;
    }
  },
  { immediate: true }
);
</script>

<style scoped>
.node-panel-drawer {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 240px;
  background: var(--color-bg-2, #f8fafc);
  border-right: 1.5px solid var(--color-border-2, #e5e7eb);
  z-index: 3000;
  box-shadow: 2px 0 12px rgba(0, 0, 0, 0.08);
  transition: width 0.2s;
  display: flex;
  flex-direction: column;
  border-top-right-radius: 16px;
  border-bottom-right-radius: 16px;
}
.drawer-header {
  display: flex;
  align-items: center;
  padding: 10px 12px 10px 16px;
  border-bottom: 1px solid var(--color-border-2, #e5e7eb);
  background: var(--color-bg-2, #fff);
  border-top-right-radius: 16px;
}
.search-icon {
  font-size: 16px;
  margin-right: 6px;
  color: var(--color-text-3, #94a3b8);
}
.search-input {
  flex: 1;
  padding: 6px 10px;
  border: 1px solid var(--color-border-2, #d1d5db);
  border-radius: 8px;
  background: var(--color-fill-2, #f1f5f9);
  font-size: 14px;
  outline: none;
  transition: border 0.2s;
  color: var(--color-text-1, #374151);
}
.search-input:focus {
  border: 1.5px solid #3b82f6;
  background: var(--color-bg-2, #fff);
}
.search-input::placeholder {
  color: var(--color-text-3, #9ca3af);
}
.min-btn {
  margin-left: 10px;
  background: var(--color-fill-2, #f1f5f9);
  border: none;
  border-radius: 50%;
  width: 28px;
  height: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 18px;
  color: var(--color-text-2, #64748b);
  cursor: pointer;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06);
  transition: background 0.2s;
}
.min-btn:hover {
  background: var(--color-fill-3, #e0e7ef);
}
.drawer-categories {
  flex: 1;
  overflow-y: auto;
  padding: 12px 0 12px 0;
}
.category {
  margin-bottom: 18px;
}
.cat-title {
  font-weight: bold;
  color: var(--color-text-1, #334155);
  margin-bottom: 6px;
  padding-left: 0;
  display: flex;
  align-items: center;
  font-size: 15px;
}
.cat-bar {
  display: inline-block;
  width: 6px;
  height: 18px;
  border-radius: 3px;
  margin-right: 8px;
}
.node-list {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  padding-left: 8px;
}
.node-item {
  display: flex;
  align-items: center;
  background: var(--color-bg-2, #fff);
  border-radius: 10px;
  padding: 6px 14px 6px 10px;
  cursor: grab;
  user-select: none;
  font-size: 15px;
  min-width: 90px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
  border-left: 6px solid var(--color-border-2, #e5e7eb);
  transition:
    box-shadow 0.2s,
    transform 0.2s;
  color: var(--color-text-1, #374151);
}
.node-item:hover {
  box-shadow: 0 4px 16px rgba(59, 130, 246, 0.12);
  border-left: 6px solid #3b82f6;
}
.node-icon {
  margin-right: 8px;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--color-fill-2, #f1f5f9);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 18px;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.04);
}
.node-label {
  font-weight: 500;
  color: var(--color-text-1, #334155);
}
.node-panel-mini {
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 28px;
  height: 56px;
  background: var(--color-bg-2, #fff);
  border-right: 1.5px solid var(--color-border-2, #e5e7eb);
  box-shadow: 2px 0 12px rgba(0, 0, 0, 0.08);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  z-index: 3001;
  border-top-right-radius: 12px;
  border-bottom-right-radius: 12px;
  color: var(--color-text-2, #64748b);
}
.node-panel-mini:hover {
  background: var(--color-fill-2, #f1f5f9);
  color: var(--color-text-1, #374151);
}
.slide-left-enter-active,
.slide-left-leave-active {
  transition: all 0.2s;
}
.slide-left-enter-from,
.slide-left-leave-to {
  transform: translateX(-100%);
  opacity: 0;
}
</style>
